/**
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef PLUGINS_ECMASCRIPT_RUNTIME_MEM_ECMA_REFERENCE_PROCESSOR_H
#define PLUGINS_ECMASCRIPT_RUNTIME_MEM_ECMA_REFERENCE_PROCESSOR_H

#include "runtime/mem/gc/reference-processor/reference_processor.h"

namespace ark {
class ObjectHeader;
class BaseClass;
namespace mem {
enum class GCPhase;
class Reference;
class GC;
}  // namespace mem
namespace ecmascript {
class EcmaVM;
}  // namespace ecmascript
}  // namespace ark

namespace ark::mem::ecmascript {

/// Mechanism for processing JS weak references
class EcmaReferenceProcessor : public ark::mem::ReferenceProcessor {
public:
    explicit EcmaReferenceProcessor(ark::ecmascript::EcmaVM *vm);

    bool IsReference(const BaseClass *baseCls, const ObjectHeader *ref,
                     const ReferenceCheckPredicateT &refPred) const override;

    void HandleReference(GC *gc, GCMarkingStackType *objectsStack, const BaseClass *baseClass,
                         const ObjectHeader *object, const ReferenceProcessPredicateT &pred) override;

    void ProcessReferences(bool concurrent, bool clearSoftReferences, GCPhase gcPhase,
                           const mem::GC::ReferenceClearPredicateT &pred) override;

    ark::mem::Reference *CollectClearedReferences() override
    {
        return nullptr;
    }

    void ScheduleForEnqueue([[maybe_unused]] Reference *clearedReferences) override
    {
        UNREACHABLE();
    }

    void Enqueue([[maybe_unused]] ark::mem::Reference *clearedReferences) override
    {
        UNREACHABLE();
    }

    size_t GetReferenceQueueSize() const override
    {
        os::memory::LockHolder lock(weakRefLock_);
        return dynWeakReferences_.size();
    }

private:
    mutable os::memory::Mutex weakRefLock_;
    PandaUnorderedSet<ObjectHeader *> dynWeakReferences_ GUARDED_BY(weakRefLock_);
    ark::ecmascript::EcmaVM *vm_;
    GC *gc_;
};

}  // namespace ark::mem::ecmascript
#endif  // PLUGINS_ECMASCRIPT_RUNTIME_MEM_ECMA_REFERENCE_PROCESSOR_H
